# -*- coding: UTF-8 -*-
# PyCharm  fast_serve
# 2024年 06月 03日
# 作者：小帅天一

from io import StringIO

import pandas as pd
import uvicorn
from fastapi import FastAPI, File, UploadFile
from starlette.middleware.cors import CORSMiddleware
from entities.RequestData import *
from entities.Response import Response
from sqlalchemy.sql import text
from sqlalchemy.orm import sessionmaker
from tools import *
import warnings
import joblib

warnings.filterwarnings('ignore')
pd.set_option('display.max_columns', None)
app = FastAPI()

# 创建数据库连接
engine = engine_of_sql()
# 创建一个Session类
Session = sessionmaker(bind=engine)
session = Session()
# 允许跨域请求的域名列表，如果要允许所有来源的跨域请求，可以将 allow_origins 设置为 ["*"]
# 如果只允许特定来源的跨域请求，可以将 allow_origins 设置为特定的域名列表，例如 ["http://localhost", "http://example.com"]
# 你也可以在 allow_origins_regex 中使用正则表达式来匹配特定的域名
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
)


@app.post("/predictHealthcare")
def health_data_predict(data: HealthData, response_model=Response):
    print(data)
    print(type(data))
    # 加载标准化对象，训练和预测数据都需要一致
    scaler = joblib.load(Config.health_scaler_model)

    # print(scaler)

    # data请求数据格式化-->转换成DataFrame-->热编码
    x = health_data_conversion(data)
    # print(x.columns)
    x = scaler.transform(x)
    model = None

    if data.mode == "lg":
        # 加载训练好的模型
        model = joblib.load(Config.health_LogisticRegression_model_path)
    elif data.mode == "dt":
        # 加载训练好的模型
        model = joblib.load(Config.health_DecisionTreeClassifier_model_path)
    elif data.mode == "knn":
        # 加载训练好的模型
        model = joblib.load(Config.health_KNeighborsClassifier_model_path)
    elif data.mode == "by":
        # 加载训练好的模型
        model = joblib.load(Config.health_GaussianNB_model_path)
    elif data.mode == "svn":
        # 加载训练好的模型
        model = joblib.load(Config.health_svm_model_path)
    elif data.mode == "rf":
        # 加载训练好的模型
        model = joblib.load(Config.health_RandomForestRegression_model_path)

    y_pred = model_predict(model, x)
    return Response(data=int(y_pred), msg="Success！", code=200)


@app.post("/predictSalary")
def salary_data_predict(data: SalaryData, response_model=Response):
    print(data)
    print(type(data))
    # 加载标准化对象，训练和预测数据都需要一致
    scaler = joblib.load(Config.salary_scaler_model)

    # print(scaler)

    # data请求数据格式化-->转换成DataFrame-->热编码
    x = salary_data_conversion(data)
    # print(x.columns)
    x = scaler.transform(x)
    model = None

    if data.mode == "lg":
        # 加载训练好的模型
        model = joblib.load(Config.salary_LogisticRegression_model_path)
    elif data.mode == "dt":
        # 加载训练好的模型
        model = joblib.load(Config.salary_DecisionTreeClassifier_model_path)
    elif data.mode == "knn":
        # 加载训练好的模型
        model = joblib.load(Config.salary_DecisionTreeClassifier_model_path)
    elif data.mode == "by":
        # 加载训练好的模型
        model = joblib.load(Config.salary_GaussianNB_model_path)
    elif data.mode == "svn":
        # 加载训练好的模型
        model = joblib.load(Config.salary_svm_model_path)
    elif data.mode == "rf":
        # 加载训练好的模型
        model = joblib.load(Config.salary_RandomForestRegression_model_path)

    y_pred = model_predict(model, x)
    return Response(data=int(y_pred), msg="Success！", code=200)


# 模型训练
@app.get('/train')
async def data_train(mode: str, mission: str):
    #   根据data中的mode 进行有选择的预测
    score = create_model(mission, mode)
    return Response(data=1, msg=f"this model's R2 score is {score}", code=200)


# 训练集上传
@app.post('/uploadFile')
async def upload_file(file: UploadFile = File(...)):
    # 读取上传的CSV文件内容
    contents = await file.read()
    # 将字节内容转换为字符串
    contents_str = contents.decode("utf-8")
    # 将CSV字符串转换为DataFrame
    df = pd.read_csv(StringIO(contents_str))
    print(df)

    # 将DataFrame中的数据插入到数据库表中
    if "gender" in df.columns:
        df = df.dropna()
        del df['id']
        df.to_sql('healthcareData', con=engine, if_exists='append', index=False)
    elif 'sex' in df.columns:
        df = df.replace(to_replace=" ?", value=np.nan)
        df = df.dropna()
        df.to_sql('salaryData', con=engine, if_exists='append', index=False)


if __name__ == '__main__':
    uvicorn.run(app, host="localhost", port=8008)
